/*
 * Copyright (C) 2015 备胎金服
 * 未经授权允许不得进行拷贝和修改
 *   http://www.btjf.com/
 */
package com.zhangman.androidgame;

import android.graphics.Color;
import android.graphics.Paint;
import com.zhangman.framework.Game;
import com.zhangman.framework.Graphics;
import com.zhangman.framework.Image;
import com.zhangman.framework.Input;
import com.zhangman.framework.Screen;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * Created by zhangman on 2016/11/1 14:59.
 * Email: zhangman523@126.com
 */
public class GameScreen extends Screen {
  enum GameState {
    Ready, Running, Paused, GameOver
  }

  GameState state = GameState.Ready;
  private static Background bg1, bg2;
  private static Robot robot;
  public static Heliboy hb, hb2;
  private Image currentSprite, character, character2, character3, heliboy, heliboy2, heliboy3,
      heliboy4, heliboy5;
  private Animation anim, hanim;
  private ArrayList tilearray = new ArrayList();

  int livesLeft = 1;
  Paint mPaint, mPaint2;

  public GameScreen(Game game) {
    super(game);

    bg1 = new Background(0, 0);
    bg2 = new Background(2160, 0);
    robot = new Robot();
    hb = new Heliboy(340, 360);
    hb2 = new Heliboy(700, 360);

    character = Assets.character;
    character2 = Assets.character2;
    character3 = Assets.character3;

    heliboy = Assets.heliboy;
    heliboy2 = Assets.heliboy2;
    heliboy3 = Assets.heliboy3;
    heliboy4 = Assets.heliboy4;
    heliboy5 = Assets.heliboy5;

    anim = new Animation();
    anim.addFrame(character, 1250);
    anim.addFrame(character2, 50);
    anim.addFrame(character3, 50);
    anim.addFrame(character2, 50);

    hanim = new Animation();
    hanim.addFrame(heliboy, 100);
    hanim.addFrame(heliboy2, 100);
    hanim.addFrame(heliboy3, 100);
    hanim.addFrame(heliboy4, 100);
    hanim.addFrame(heliboy5, 100);
    hanim.addFrame(heliboy4, 100);
    hanim.addFrame(heliboy3, 100);
    hanim.addFrame(heliboy2, 100);

    currentSprite = anim.getImage();

    loadMap();

    mPaint = new Paint();
    mPaint.setTextSize(30);
    mPaint.setTextAlign(Paint.Align.CENTER);
    mPaint.setAntiAlias(true);
    mPaint.setColor(Color.WHITE);

    mPaint2 = new Paint();
    mPaint2.setTextSize(100);
    mPaint2.setTextAlign(Paint.Align.CENTER);
    mPaint2.setAntiAlias(true);
    mPaint2.setColor(Color.WHITE);
  }

  private void loadMap() {
    ArrayList lines = new ArrayList();
    int width = 0;
    int height = 0;
    Scanner scanner = new Scanner(SampleGame.map);
    while (scanner.hasNextLine()) {
      String line = scanner.nextLine();
      if (line == null) {
        break;
      }
      if (!line.startsWith("!")) {
        lines.add(line);
        width = Math.max(width, line.length());
      }
    }
    height = lines.size();
    for (int j = 0; j < 12; j++) {
      String line = (String) lines.get(j);
      for (int i = 0; i < width; i++) {
        if (i < line.length()) {
          char ch = line.charAt(i);
          Tile t = new Tile(i, j, Character.getNumericValue(ch));
          tilearray.add(t);
        }
      }
    }
  }

  @Override public void update(float deltaTime) {
    List<Input.TouchEvent> touchEvents = mGame.getInput().getTouchEvents();
    if (state == GameState.Ready) {
      updateReady(touchEvents);
    }
    if (state == GameState.Running) {
      updateRunning(touchEvents, deltaTime);
    }
    if (state == GameState.Paused) {
      updatePaused(touchEvents);
    }
    if (state == GameState.GameOver) {
      updateGameOver(touchEvents);
    }
  }

  private void updateReady(List<Input.TouchEvent> touchEvents) {
    if (touchEvents.size() > 0) {
      state = GameState.Running;
    }
  }

  private void updateRunning(List<Input.TouchEvent> touchEvents, float deltaTime) {
    //1.All tuoch input is handed here;
    int len = touchEvents.size();
    for (int i = 0; i < len; i++) {
      Input.TouchEvent event = touchEvents.get(i);
      if (event.type == Input.TouchEvent.TOUCH_DOWN) {
        if (inBounds(event, 0, 285, 65, 65)) {
          robot.jump();
          currentSprite = anim.getImage();
          robot.setDucked(false);
        } else if (inBounds(event, 0, 350, 65, 65)) {
          if (robot.isDucked() == false && robot.isJumped() == false && robot.isReadyToFire()) {
            robot.shoot();
          }
        } else if (inBounds(event, 0, 415, 65, 65) && robot.isJumped() == false) {
          currentSprite = Assets.characterDown;
          robot.setDucked(true);
          robot.setSpeedX(0);
        }
        if (event.x > 400) {
          robot.moveRight();
          robot.setMovingRight(true);
        }
      }
      if (event.type == Input.TouchEvent.TOUCH_UP) {
        if (inBounds(event, 0, 415, 65, 65)) {
          currentSprite = anim.getImage();
          robot.setDucked(false);
        }
        if (inBounds(event, 0, 0, 35, 35)) {
          pause();
        }
        if (event.x > 400) {
          robot.stopRight();
        }
      }
    }
    //2.Check miscellaneous events like death;
    if (livesLeft == 0) {
      state = GameState.GameOver;
    }
    //3.Call individual update() methods here.
    //This is where all the game updates happen.
    //For example, robot.update();
    robot.update();
    if (robot.isJumped()) {
      currentSprite = Assets.characterJump;
    } else if (!robot.isJumped() && !robot.isDucked()) {
      currentSprite = anim.getImage();
    }
    ArrayList projectiles = robot.getProjectiles();
    for (int i = 0; i < projectiles.size(); i++) {
      Projectile p = (Projectile) projectiles.get(i);
      if (p.isVisible()) {
        p.update();
      } else {
        projectiles.remove(i);
      }
    }
    updateTiles();
    hb.update();
    hb2.update();
    bg1.update();
    bg2.update();
    animate();
    if (robot.getCenterY() > 500) {
      state = GameState.GameOver;
    }
  }

  private void animate() {
    anim.update(10);
    hanim.update(10);
  }

  private void updateTiles() {
    for (int i = 0; i < tilearray.size(); i++) {
      Tile t = (Tile) tilearray.get(i);
      t.update();
    }
  }

  private boolean inBounds(Input.TouchEvent event, int x, int y, int width, int height) {
    if (event.x > x && event.x < x + width - 1 && event.y > y && event.y < y + height - 1) {
      return true;
    } else {
      return false;
    }
  }

  private void updatePaused(List<Input.TouchEvent> touchEvents) {
    int len = touchEvents.size();
    for (int i = 0; i < len; i++) {
      Input.TouchEvent event = touchEvents.get(i);
      if (event.type == Input.TouchEvent.TOUCH_UP) {
        if (inBounds(event, 0, 0, 800, 240)) {
          if (!inBounds(event, 0, 0, 35, 35)) {
            resume();
          }
        }
        if (inBounds(event, 0, 240, 800, 240)) {
          nullify();
          goToMenu();
        }
      }
    }
  }

  private void updateGameOver(List<Input.TouchEvent> touchEvents) {
    int len = touchEvents.size();
    for (int i = 0; i < len; i++) {
      Input.TouchEvent event = touchEvents.get(i);
      if (event.type == Input.TouchEvent.TOUCH_DOWN) {
        if (inBounds(event, 0, 0, 800, 480)) {
          nullify();
          mGame.setScreen(new MainMenuScreen(mGame));
          return;
        }
      }
    }
  }

  private void goToMenu() {
    mGame.setScreen(new MainMenuScreen(mGame));
  }

  private void nullify() {
    mPaint = null;
    bg1 = null;
    bg2 = null;
    robot = null;
    hb = null;
    hb2 = null;
    currentSprite = null;
    character = null;
    character2 = null;
    character3 = null;
    heliboy = null;
    heliboy2 = null;
    heliboy3 = null;
    heliboy4 = null;
    heliboy5 = null;
    anim = null;
    hanim = null;
    System.gc();
  }

  @Override public void pain(float deltaTime) {
    Graphics g = mGame.getGraphics();
    //First draw the game elements.
    //Example:
    //g.drawImage(Assets.background,0,0);
    //g.drawImage(Assets.character,characterX,characterY);
    g.drawImage(currentSprite, robot.getCenterX() - 61, robot.getCenterY() - 48);
    g.drawImage(hanim.getImage(), hb.getCenterX() - 48, hb.getCenterY() - 48);
    g.drawImage(hanim.getImage(), hb2.getCenterX() - 48, hb2.getCenterY() - 48);
    //Secondly, draw the UI above the game elements.
    if (state == GameState.Ready) {
      drawReadyUI();
    }
    if (state == GameState.Running) {
      drawRunningUI();
    }
    if (state == GameState.Paused) {
      drawPausedUI();
    }
    if (state == GameState.GameOver) {
      drawGameOverUI();
    }
  }

  private void drawReadyUI() {
    Graphics g = mGame.getGraphics();
    g.drawARGB(155, 0, 0, 0);
    g.drawString("Tap to Start.", 640, 300, mPaint);
  }

  private void drawRunningUI() {
    Graphics g = mGame.getGraphics();
    g.drawImage(Assets.button, 0, 285, 0, 0, 65, 65);
    g.drawImage(Assets.button, 0, 350, 0, 65, 65, 65);
    g.drawImage(Assets.button, 0, 415, 0, 130, 65, 65);
    g.drawImage(Assets.button, 0, 0, 0, 195, 35, 35);
  }

  private void drawPausedUI() {
    Graphics g = mGame.getGraphics();
    g.drawARGB(155, 0, 0, 0);
    g.drawString("Resume", 400, 165, mPaint2);
    g.drawString("Menu", 400, 365, mPaint2);
  }

  private void drawGameOverUI() {
    Graphics g = mGame.getGraphics();
    g.drawRect(0, 0, 1281, 801, Color.BLACK);
    g.drawString("GAME OVER", 640, 300, mPaint);
    g.drawString("Tap to return.", 400, 290, mPaint);
  }

  @Override public void pause() {
    if (state == GameState.Running) {
      state = GameState.Paused;
    }
  }

  @Override public void resume() {
    if (state == GameState.Paused) {
      state = GameState.Running;
    }
  }

  @Override public void dispose() {

  }

  @Override public void backButton() {
    pause();
  }

  public static Background getBg2() {
    return bg2;
  }

  public static void setBg2(Background bg2) {
    GameScreen.bg2 = bg2;
  }

  public static Background getBg1() {
    return bg1;
  }

  public static void setBg1(Background bg1) {
    GameScreen.bg1 = bg1;
  }

  public static Robot getRobot() {
    return robot;
  }

  public static void setRobot(Robot robot) {
    GameScreen.robot = robot;
  }
}
